﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Dynamic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;

namespace Core.Utility.Helper
{
    /// <summary>
    /// 值类型转换助手类
    /// </summary>
    public static class ValueTypeConvertHelper
    {
        ///// <summary>
        ///// 解决 Razor 中的动态匿名类型导致 RuntimeBinderException；将动态匿名对象转换为 ExpandoObject
        ///// 解决代码参考 <see href="https://stackoverflow.com/questions/5120317/dynamic-anonymous-type-in-razor-causes-runtimebinderexception/5670899#5670899"/>
        ///// </summary>
        ///// <param name="anonymousObject"></param>
        ///// <returns></returns>
        //public static ExpandoObject? ToExpandoObject(this object anonymousObject)
        //{
        //    IDictionary<string, object> expando = new ExpandoObject();
        //    foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(anonymousObject))
        //    {
        //        var obj = propertyDescriptor.GetValue(anonymousObject);
        //        expando.Add(propertyDescriptor.Name, obj);
        //    }
        //    return (ExpandoObject)expando;
        //}

        /// <summary>
        /// 将 DateTimeOffset 转换成本地 DateTime
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        public static DateTime ConvertToDateTime(this DateTimeOffset dateTime)
        {
            if (dateTime.Offset.Equals(TimeSpan.Zero))
                return dateTime.UtcDateTime;
            if (dateTime.Offset.Equals(TimeZoneInfo.Local.GetUtcOffset(dateTime.DateTime)))
                return dateTime.ToLocalTime().DateTime;
            else
                return dateTime.DateTime;
        }

        /// <summary>
        /// 将 DateTimeOffset? 转换成本地 DateTime?
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        public static DateTime? ConvertToDateTime(this DateTimeOffset? dateTime)
        {
            return dateTime.HasValue ? dateTime.Value.ConvertToDateTime() : null;
        }

        /// <summary>
        /// 将 DateTime 转换成 DateTimeOffset
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        public static DateTimeOffset ConvertToDateTimeOffset(this DateTime dateTime)
        {
            return DateTime.SpecifyKind(dateTime, DateTimeKind.Local);
        }

        /// <summary>
        /// 将 DateTime? 转换成 DateTimeOffset?
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        public static DateTimeOffset? ConvertToDateTimeOffset(this DateTime? dateTime)
        {
            return dateTime.HasValue ? dateTime.Value.ConvertToDateTimeOffset() : null;
        }

        /// <summary>
        /// 将时间戳转换为 DateTime
        /// </summary>
        /// <param name="timestamp"></param>
        /// <returns></returns>
        internal static DateTime ConvertToDateTime(this long timestamp)
        {
            var timeStampDateTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            var digitCount = (int)Math.Floor(Math.Log10(timestamp) + 1);

            if (digitCount != 13 && digitCount != 10)
            {
                throw new ArgumentException("Data is not a valid timestamp format.");
            }

            return (digitCount == 13
                ? timeStampDateTime.AddMilliseconds(timestamp)  // 13 位时间戳
                : timeStampDateTime.AddSeconds(timestamp)).ToLocalTime();   // 10 位时间戳
        }


        /// <summary>
        /// 转换类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <param name="defaultT"></param>
        /// <returns></returns>
        public static T? ChangeType<T>(this object? value, T? defaultT = default(T))
        {
            T? result = defaultT;
            try
            {
                object? resultObj = Convert.ChangeType(value, typeof(T));
                result = (T?)resultObj;
            }
            catch
            {

            }
            return result;
        }

        /// <summary>
        /// 通过字符串转换为指定的类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="str"></param>
        /// <param name="defaultT"></param>
        /// <returns></returns>
        public static T? ChangeTypeByString<T>(this string str, T? defaultT = default(T))
        {
            var typeConverter = System.ComponentModel.TypeDescriptor.GetConverter(typeof(T));
            if (typeConverter.CanConvertTo(typeof(T)))
                return (T?)typeConverter.ConvertFromString(str);
            return defaultT;
        }

        /// <summary>
        /// 通过字符串转换为指定的类型
        /// </summary>
        /// <param name="str"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static object? ChangeTypeByString(this string str, Type type)
        {
            var typeConverter = System.ComponentModel.TypeDescriptor.GetConverter(type);
            if (typeConverter.CanConvertFrom(typeof(string)))
                return typeConverter.ConvertFromString(str);
            return null;
        }

        /// <summary>
        /// 使用指定的格式、区域性特定的格式信息和样式将日期和时间的指定范围表示形式转换为其等效的 System.DateTime
        /// </summary>
        /// <param name="s">要转换的日期和时间的字符</param>
        /// <param name="format">包含表示用于定义所需的 s 格式的格式说明符的字符。</param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static DateTime DateTimeParseExact(this string s, string format = "yyyy-MM-dd HH:mm:ss", DateTime defaultValue = default)
        {
            DateTime res = defaultValue;
            try
            {
                DateTime.TryParseExact(s, format, CultureInfo.CurrentCulture, DateTimeStyles.None, out res);
            }
            catch
            {

            }
            return res;
        }

        /// <summary>
        /// object 转 Decimal
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static decimal ToDecimal(this object? value, decimal defaultValue = 0)
        {
            decimal result;
            try
            {
                result = (value == null || value == DBNull.Value) ? defaultValue : Convert.ToDecimal(value);
            }
            catch
            {
                result = defaultValue;
            }
            return result;
        }

        /// <summary>
        /// object 转 string, 主要处理 string? => string
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static string GetValueOrDefault(this object? value, string defaultValue = "")
        {
            string result = defaultValue;
            if (value != null)
            {
                try
                {
                    string? cr = Convert.ToString(value);
                    result = (value == null || value == DBNull.Value || cr == null) ? defaultValue : cr;
                }
                catch
                {
                    result = defaultValue;
                }
            }
            return result;
        }

        /// <summary>
        /// 转换为Decimail? 可对精度进行处理
        /// </summary>
        /// <param name="value">被转换的值</param>
        /// <param name="scale">截断精度，该值为NULL则不做任何处理</param>
        /// <param name="defaultValue">转换失败的默认值</param>
        public static decimal ToDecimalPrecision(this object? value, int? scale = null, decimal defaultValue = 0)
        {

            decimal result;
            try
            {
                result = (value == null || value == DBNull.Value) ? defaultValue : Convert.ToDecimal(value);
                if (scale != null)
                {
                    int iScale = ToInt(scale);
                    string? numToString = result.ToString();
                    int? index = numToString?.IndexOf(".");
                    int? length = numToString?.Length;
                    if (index != -1)
                    {
                        string res = string.Format("{0}.{1}",
                            numToString?.Substring(0, index.GetValueOrDefault(0)),
                            numToString?.Substring(index.GetValueOrDefault(0) + 1, Math.Min(length.GetValueOrDefault(0) - index.GetValueOrDefault(0) - 1, iScale)));
                        result = ToDecimalPrecision(res, null, defaultValue);
                    }
                }
            }
            catch
            {
                result = defaultValue;
            }
            return result;
        }

        /// <summary>
        ///  Decimal 绝对值
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static decimal? ToDecimalAbs(this decimal? value)
        {
            decimal? result;
            try
            {
                if (value == null)
                {
                    result = null;
                }
                else if (value == 0)
                {
                    return 0;
                }
                else
                {
                    result = Math.Abs(ToDecimal(value, 0));
                }
            }
            catch
            {
                result = null;
            }
            return result;
        }

        /// <summary>
        /// Decimal 负数，将传入的值求绝对值并*-1
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static decimal ToDecimalNegative(this decimal value)
        {
            decimal result = 0;
            try
            {
                result = Math.Abs(ToDecimal(value, 0)) * -1;
            }
            catch
            {

            }
            return result;
        }

        /// <summary>
        /// object 转 int
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <returns></returns>
        public static int ToInt(this object? value, int defaultValue = 0)
        {
            int result;
            try
            {
                result = (value == null || value == DBNull.Value) ? defaultValue : Convert.ToInt32((value));
            }
            catch
            {
                result = defaultValue;
            }
            return result;
        }


        /// <summary>
        /// object 转 uint
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <returns></returns>
        public static uint ToUInt(this object? value, uint defaultValue = 0)
        {
            uint result;
            try
            {
                result = (value == null || value == DBNull.Value) ? defaultValue : Convert.ToUInt32((value));
            }
            catch
            {
                result = defaultValue;
            }
            return result;
        }


        /// <summary>
        /// object 转 uint?
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <returns></returns>
        public static uint? ToUIntNullable(this object? value, uint? defaultValue = 0)
        {
            uint? result;
            try
            {
                result = (value == null || value == DBNull.Value) ? defaultValue : Convert.ToUInt32((value));
            }
            catch
            {
                result = defaultValue;
            }
            return result;
        }

        /// <summary>
        /// object 转 uint
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <returns></returns>
        public static ulong ToULong(this object? value, ulong defaultValue = 0)
        {
            ulong result;
            try
            {
                result = (value == null || value == DBNull.Value) ? defaultValue : Convert.ToUInt64((value));
            }
            catch
            {
                result = defaultValue;
            }
            return result;
        }

        /// <summary>
        /// object 转 ulong?
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <returns></returns>
        public static ulong ToULongNullable(this object? value, ulong defaultValue = 0)
        {
            ulong result;
            try
            {
                result = (value == null || value == DBNull.Value) ? defaultValue : Convert.ToUInt64((value));
            }
            catch
            {
                result = defaultValue;
            }
            return result;
        }

        /// <summary>
        /// double? 转 double
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <returns></returns>
        public static double ToDouble(this object? value, double defaultValue = 0)
        {
            double result;
            try
            {
                result = (value == null || value == DBNull.Value) ? defaultValue : Convert.ToDouble(value);
            }
            catch
            {
                result = defaultValue;
            }
            return result;
        }

        /// <summary>
        /// object 转 long
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <returns></returns>
        public static long? ToLong(this object? value, long defaultValue = 0)
        {
            long result;
            try
            {
                result = (value == null || value == DBNull.Value) ? defaultValue : Convert.ToInt64(value);
            }
            catch
            {
                result = defaultValue;
            }
            return result;
        }

        /// <summary>
        /// object 转 float
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <returns></returns>
        public static float ToFloat(this object? value, float defaultValue = 0)
        {
            float result;
            try
            {
                result = (value == null || value == DBNull.Value) ? defaultValue : Convert.ToSingle(value);
            }
            catch
            {
                result = defaultValue;
            }
            return result;
        }

        /// <summary>
        /// object 转 string
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <returns></returns>
        public static string? ToString(this object? value, string? defaultValue = "")
        {
            string? result;
            try
            {
                result = (value == null || value == DBNull.Value) ? defaultValue : value.ToString();
            }
            catch
            {
                result = defaultValue;
            }
            return result;
        }

        /// <summary>
        /// bool? 转 bool
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <returns></returns>
        public static bool ToBoolean(this object value, bool defaultValue = false)
        {
            bool result;
            try
            {
                result = (value == null || value == DBNull.Value) ? defaultValue : Convert.ToBoolean(value);
            }
            catch
            {
                result = defaultValue;
            }
            return result;
        }

        /// <summary>
        /// DateTime? 转 DateTime
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static DateTime ToDateTime(this object? value)
        {
            DateTime result;
            try
            {
                result = (value == null || value == DBNull.Value) ? DateTime.MinValue : Convert.ToDateTime(value);
            }
            catch
            {
                result = DateTime.MinValue;
            }
            return result;
        }

        /// <summary>
        /// 将Utc时间转换为本地时间
        /// </summary>
        /// <param name="utcDateTime"></param>
        /// <returns></returns>
        public static DateTime? ToLocalDateTime(this DateTime? utcDateTime)
        {
            DateTime? result = null;
            if (utcDateTime != null)
            {
                result = utcDateTime.Value.ToLocalDateTime();
            }
            return result;
        }

        /// <summary>
        /// 将Utc时间转换为本地时间
        /// </summary>
        /// <param name="utcDateTimeOffset"></param>
        /// <returns></returns>
        public static DateTime? ToLocalDateTime(this DateTimeOffset? utcDateTimeOffset)
        {
            DateTime? result = null;
            if (utcDateTimeOffset != null)
            {
                result = utcDateTimeOffset.Value.ToLocalDateTime();
            }
            return result;
        }

        /// <summary>
        /// 将Utc时间转换为本地时间
        /// </summary>
        /// <param name="utcDateTime"></param>
        /// <returns></returns>
        public static DateTime? ToLocalDateTime(this DateTime utcDateTime)
        {
            return TimeZoneInfo.ConvertTime(utcDateTime, TimeZoneInfo.Local);
        }

        /// <summary>
        /// 将Utc时间转换为本地时间
        /// </summary>
        /// <param name="utcDateTimeOffset"></param>
        /// <returns></returns>
        public static DateTime? ToLocalDateTime(this DateTimeOffset utcDateTimeOffset)
        {
            return TimeZoneInfo.ConvertTime(utcDateTimeOffset, TimeZoneInfo.Local).DateTime;
        }

        /// <summary>
        /// 将本地时间转换为Utc时间
        /// </summary>
        /// <param name="localDateTime"></param>
        /// <returns></returns>
        public static DateTime? ToUtcTime(this DateTime? localDateTime)
        {
            DateTime? result = null;
            if (localDateTime != null)
            {
                localDateTime.Value.ToUtcTime();
            }
            return result;
        }

        /// <summary>
        /// 将本地时间转换为Utc时间
        /// </summary>
        /// <param name="localDateTimeOffset"></param>
        /// <returns></returns>
        public static DateTime? ToUtcTime(this DateTimeOffset? localDateTimeOffset)
        {
            DateTime? result = null;
            if (localDateTimeOffset != null)
            {
                result = localDateTimeOffset.Value.ToUtcTime();
            }
            return result;
        }

        /// <summary>
        /// 将本地时间转换为Utc时间
        /// </summary>
        /// <param name="localDateTime"></param>
        /// <returns></returns>
        public static DateTime? ToUtcTime(this DateTime localDateTime)
        {
            return TimeZoneInfo.ConvertTime(localDateTime, TimeZoneInfo.Utc);
        }

        /// <summary>
        /// 将本地时间转换为Utc时间
        /// </summary>
        /// <param name="localDateTimeOffset"></param>
        /// <returns></returns>
        public static DateTime? ToUtcTime(this DateTimeOffset localDateTimeOffset)
        {
            return TimeZoneInfo.ConvertTime(localDateTimeOffset, TimeZoneInfo.Utc).DateTime;
        }

        /// <summary>
        /// DateTime? 转 DateTime
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <returns></returns>
        public static DateTime ToDateTime(this object? value, DateTime defaultValue)
        {
            DateTime result;
            try
            {
                result = (value == null || value == DBNull.Value) ? defaultValue : Convert.ToDateTime(value);
            }
            catch
            {
                result = defaultValue;
            }
            return result;
        }

        /// <summary>
        /// object 转 byte
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <returns></returns>
        public static byte? ToByte(this object? value, byte? defaultValue = 0)
        {
            byte? result;
            try
            {
                result = (value == null || value == DBNull.Value) ? defaultValue : Convert.ToByte(value);
            }
            catch
            {
                result = defaultValue;
            }
            return result;
        }

        /// <summary>
        /// object 转 Char
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <returns></returns>
        public static char? ToChar(this object? value, char? defaultValue = '\0')
        {
            char? result;
            try
            {
                result = (value == null || value == DBNull.Value) ? defaultValue : Convert.ToChar(value);
            }
            catch
            {
                result = defaultValue;
            }
            return result;
        }

        /// <summary>
        /// object 转 SByte
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <returns></returns>
        public static sbyte? ToSByte(this object? value, sbyte? defaultValue = 0)
        {
            sbyte? result;
            try
            {
                result = (value == null || value == DBNull.Value) ? defaultValue : Convert.ToSByte(value);
            }
            catch
            {
                result = defaultValue;
            }
            return result;
        }

        /// <summary>
        /// 将一个值类型转换为可为空类型
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="value">值</param>
        /// <returns></returns>
        public static T? ToNullable<T>(this T value)
            where T : struct
        {
            T? res = new T?(value);
            return res;
        }

        /// <summary>
        /// 将一个对象转换为指定类型的可为空类型
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="value">值</param>
        /// <returns></returns>
        public static T? ToNullable<T>(this object value)
            where T : struct
        {
            T? res = new T?();
            try
            {
                res = value as T?;
            }
            catch
            {
                res = null;
            }
            return res;
        }

        /// <summary>
        /// 将一个对象转换为指定类型的可为空类型
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="value">值</param>
        /// <param name="defaultValue">值</param>
        /// <returns></returns>
        public static T? ToNullable<T>(this object value, T defaultValue)
            where T : struct
        {
            T? res = ToNullable<T>(value);
            return res;
        }

        /// <summary>
        /// DataRow转为对象，DataRow指定值不存在或列名错误，返回指定的默认值
        /// </summary>
        /// <param name="row"></param>
        /// <param name="rowName"></param>
        /// <param name="defaultValue">默认值</param>
        /// <returns></returns>
        public static object? DataRowToOjbect(this DataRow row, string rowName, object? defaultValue = null)
        {
            object? res = defaultValue;
            try
            {
                res = row[rowName];
            }
            catch
            {

            }
            return res;
        }

        /// <summary>
        /// DataRowView转为对象，DataRow指定值不存在或列名错误，返回指定的默认值
        /// </summary>
        /// <param name="row"></param>
        /// <param name="rowName"></param>
        /// <param name="defaultValue">默认值</param>
        /// <returns></returns>
        public static object? DataRowViewToOjbect(this DataRowView row, string rowName, object? defaultValue = null)
        {
            object? res = defaultValue;
            try
            {
                res = row[rowName];
            }
            catch
            {

            }
            return res;
        }

        /// <summary>
        /// String转Base64 字符串（Utf8编码）
        /// 反转方法 <see cref="Base64StringToUtf8String(string, string)"/>
        /// </summary>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static string? ToUtf8Base64String(this string? value, string? defaultValue = null)
        {
            string? res = defaultValue;
            try
            {
                if (!string.IsNullOrEmpty(value))
                {
                    var bytes = Encoding.UTF8.GetBytes(value);
                    res = Convert.ToBase64String(bytes);
                }
            }
            catch
            {

            }
            return res;
        }

        /// <summary>
        /// Base64字符串转字符串(Utf8编码)
        /// 字符串转换方法 <see cref="ToUtf8Base64String(string, string)"/>
        /// </summary>
        /// <returns></returns>
        public static string? Base64StringToUtf8String(this string? value, string? defaultValue = null)
        {
            string? res = defaultValue;
            try
            {
                if (!string.IsNullOrEmpty(value))
                {
                    var bytes = Convert.FromBase64String(value);
                    res = Encoding.UTF8.GetString(bytes);
                }
            }
            catch
            {

            }
            return res;
        }

        /// <summary>
        /// DateTime字符串转DateTime
        /// </summary>
        /// <param name="dateTimeString">日期时间字符串</param>
        /// <param name="dateTimeFormate">日期时间格式化</param>
        /// <param name="defaultDateTime">默认时间</param>
        /// <returns></returns>
        public static DateTime? DateTimeStringToDateTime(this string dateTimeString, string dateTimeFormate = "yyyyMMdd", DateTime? defaultDateTime = null)
        {
            DateTime? res = defaultDateTime;
            try
            {
                res = DateTime.ParseExact(dateTimeString, dateTimeFormate, Thread.CurrentThread.CurrentCulture);
            }
            catch
            {

            }
            return res;
        }

        /// <summary>
        /// 是否为数值类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static bool IsNumericType(this Type type)
        {
            return !type.IsClass && !type.IsInterface && type.GetInterfaces().Any(q => q == typeof(IFormattable));
        }

        /// <summary>
        /// Unix时间戳转换为日期类型
        /// </summary>
        /// <param name="timeStamp">时间戳</param>
        /// <returns></returns>
        public static DateTime UnixTimeToDateTime(this string timeStamp)
        {
            //DateTime dateTimeStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            //long lTime = long.Parse(timeStamp + "0000000");
            //TimeSpan toNow = new TimeSpan(lTime);
            //return dateTimeStart.Add(toNow);
            DateTime dateTime = DateTime.MinValue;
            long lTimeStamp = 0;
            try
            {
                lTimeStamp = Convert.ToInt64(timeStamp);
                //dateTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)).AddSeconds(lTimeStamp);
                dateTime = DateTimeOffset.FromUnixTimeSeconds(lTimeStamp).ToLocalTime().DateTime;
            }
            catch
            {

            }
            return dateTime;
        }

        /// <summary>
        /// 尝试转换为 <see cref="KeyValuePair{TKey, TValue}"/>
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static KeyValuePair<TKey, TValue> ToKeyValuePair<TKey, TValue>(this object obj, KeyValuePair<TKey, TValue> defaultValue = default)
        {
            KeyValuePair<TKey, TValue>  result = defaultValue;
            if (obj is KeyValuePair<TKey, TValue> convertResult)
            {
                result = convertResult;
            }
            return result;
        }


        /// <summary>
        /// 尝试转换为 <see cref="Dictionary{TKey, TValue}"/>
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static Dictionary<TKey, TValue>? ToDictionary<TKey, TValue>(this object obj, Dictionary<TKey, TValue>? defaultValue = default) where TKey:notnull
        {
            Dictionary<TKey, TValue>? result = defaultValue;
            if (obj is Dictionary<TKey, TValue> convertResult)
            {
                result = convertResult;
            }
            return result;
        }

        /// <summary>
        /// 尝试转换为 <see cref="Dictionary{dynamic, dynamic}"/>
        /// </summary>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static Dictionary<dynamic, dynamic>? ToDynamicDictionary(this object obj, Dictionary<dynamic, dynamic>? defaultValue = default)
        {
            Dictionary<dynamic, dynamic>? result = defaultValue;
            if (result != null)
            {
                if(obj.IsTargetType(typeof(Dictionary<,>)))
                {
                    foreach (dynamic kvp in (IEnumerable)obj)
                    {
                        result.Add(kvp.Key, kvp.Value);
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// 尝试转换为 <see cref="List{T}"/>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static List<T>? ToList<T>(this object obj, List<T>? defaultValue = default)
        {            
            List<T>? result = defaultValue;
            if (obj is List<T> convertResult)
            {
                result = convertResult;
            }
            return result;
        }

        /// <summary>
        /// 尝试转换为 <see cref="IEnumerable{T}"/>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="defaultValue">转换失败的默认值</param>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static IEnumerable<T>? ToIEnumerable<T>(this object obj, IEnumerable<T>? defaultValue = default)
        {
            IEnumerable<T>? result = defaultValue;
            if (obj is IEnumerable<T> convertResult)
            {
                result = convertResult;
            }
            return result;
        }

        /// <summary>
        /// 类型转换
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static T Parse<T>(this object value,T defaultValue) 
        {
            try
            {
                var type = typeof(T);
                var nullableType = Nullable.GetUnderlyingType(type);
                if (nullableType is not null)
                {
                    //可为空类型
                    return (T)Convert.ChangeType(value, nullableType);
                }
                return (T)Convert.ChangeType(value, type);
            }
            catch
            {
                return defaultValue;
            }
        }


        /// <summary>
        /// 类型转换(转换为可为空类型)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <param name="defaultValue"></param>
        /// <returns></returns>
        public static T? ParseNullable<T>(this object value, T? defaultValue = default)
        {
            try
            {
                var type = typeof(T);
                var nullableType = Nullable.GetUnderlyingType(type);
                if (nullableType is not null)
                {
                    //可为空类型
                    return (T)Convert.ChangeType(value, nullableType);
                }
                return (T)Convert.ChangeType(value, type);
            }
            catch
            {
                return defaultValue;
            }
        }
    }
}
